#ifndef __OJ_MODEL_HPP__
#define __OJ_MODEL_HPP__
// OJ题库与数据交互
#include <iostream>
#include <unordered_map>
#include <string>
#include <fstream>
#include <cstring>
#include "./mysql-connect/include/mysql.h"// 引用c-mysql-connect

#include "../common/util.hpp"
#include "../common/log.hpp"

// mysql版本
namespace ns_model
{
    using namespace ns_util;
    using namespace ns_log;

    // 每一个题目独享的内存细节
    struct Question
    {
        std::string number;  // 题目编号
        std::string title;  // 题目标题
        std::string star;  // 题目难度
        int cpu_commit;  // 运行时间限制S
        int mem_commit;  // 内存占用限制KB

        std::string desc;  // 文件描述
        std::string header;  // 用户预设代码
        std::string tail;  // 测试代码
        std::string test_input;  // 测试用户代码
    };

    const std::string oj_table_name = "oj_questions";
    const std::string oj_host = "47.94.211.237";
    const std::string oj_user = "lyl";
    const std::string oj_password = "Lyl123456.";
    const std::string oj_db = "oj";
    const unsigned int oj_port = 3306;

    class Model
    {
    public:
        Model()
        {}

        ~Model()
        {}

        bool InsertQuestion(const Question& q) 
        {
            std::stringstream sql;
            sql << "INSERT INTO oj_questions (number, title, star, description, header, tail, test_input, cpu_commit, mem_commit) VALUES ("
                << q.number << ", '"
                << q.title << "', "
                << q.star << ", '"
                << q.desc << "', '"
                << q.header << "', '"
                << q.tail << "', '"
                << q.test_input << "', "
                << q.cpu_commit << ", "
                << q.mem_commit << ")";

            std::string sqlQuery = sql.str();
            std::cout << "执行 SQL: " << sqlQuery << std::endl; // 🔹 打印 SQL 语句

            bool result = ExecuteUpdate(sqlQuery);
            if (!result) {
                std::cerr << "SQL 执行失败: "  << std::endl; // 🔹 打印 SQL 失败原因
            }
            return result;
        }

        bool SaveQuestion(const Question& q) 
        {
            std::string sql = "INSERT INTO oj_questions VALUES("
                "'" + q.number + "',"
                "'" + q.title + "',"
                "'" + q.star + "',"
                "'" + q.desc + "',"
                "'" + q.header + "',"
                "'" + q.tail + "',"
                + std::to_string(q.cpu_commit) + ","
                + std::to_string(q.mem_commit) + ","
                "'" + q.test_input + "')"
                " ON DUPLICATE KEY UPDATE "
                "title=VALUES(title), star=VALUES(star),`desc`=VALUES(`desc`)";
            return ExecuteUpdate(sql);
        }

        bool DeleteQuestion(const std::string& number) 
        {
            std::string sql = "DELETE FROM oj_questions WHERE number=" + number;
            return ExecuteUpdate(sql);
        }
        // bool DeleteQuestion(int number) 
        // {
        //     std::string sql = "DELETE FROM oj_questions WHERE number=" + std::to_string(number);
        //     return ExecuteUpdate(sql);
        // }
        bool ExecuteUpdate(const std::string& sql) 
        {
            MYSQL* conn = mysql_init(nullptr);
            if (!conn) {
                std::cerr << "MySQL 初始化失败" << std::endl;
                return false;
            }

            if (!mysql_real_connect(conn, "47.94.211.237", "lyl", "Lyl123456.", "oj", 3306, nullptr, 0)) {
                std::cerr << "数据库连接失败: " << mysql_error(conn) << std::endl;
                mysql_close(conn);
                return false;
            }

            if (mysql_set_character_set(conn, "utf8mb4") != 0) {
                std::cerr << "设置 UTF-8 失败: " << mysql_error(conn) << std::endl;
                mysql_close(conn);
                return false;
            }
            
            std::cout << "执行 SQL: " << sql << std::endl;  // 打印 SQL 语句

            if (mysql_query(conn, sql.c_str()) != 0) {
                std::cerr << "SQL 执行失败: " << mysql_error(conn) << std::endl;
                mysql_close(conn);
                return false;
            }

            mysql_close(conn);
            return true;
        }
        // bool ExecuteUpdate(const std::string& sql) 
        // {
        //     MYSQL* conn = mysql_init(nullptr);
        //     // ...数据库连接和查询...
        //     return mysql_query(conn, sql.c_str()) == 0;
        // }

        bool AddQuestion(const Question& q) 
        {
            MYSQL* conn = mysql_init(nullptr);
            if (!mysql_real_connect(conn, oj_host.c_str(), oj_user.c_str(), oj_password.c_str(), oj_db.c_str(), oj_port, nullptr, 0)) 
            {
                LOG(FATAL) << "数据库连接失败\n";
                return false;
            }
    		std::string sql = "INSERT INTO oj_questions VALUES("
        	"'" + q.number + "', "
       		"'" + q.title + "', "
        	"'" + q.star + "', "
        	"'" + q.desc + "', "
        	"'" + q.header + "', "
        	"'" + q.tail + "', "
        	+ std::to_string(q.cpu_commit) + ", "
        	+ std::to_string(q.mem_commit) + ", "
        	"'" + q.test_input + "');";
            int ret = mysql_query(conn, sql.c_str());
            mysql_close(conn);
            return (ret == 0);
        }



        // 执行sql语句处
        bool QueryMySql(const std::string& sql, std::vector<Question>& v)
        {
            // c连接mysql库，创建mysql对象-初始化mysql句柄
            MYSQL* oj_client = mysql_init(nullptr);
            // 连接数据库，连接失败返回nullptr
            if (nullptr == mysql_real_connect(oj_client, oj_host.c_str(), oj_user.c_str(), oj_password.c_str(), oj_db.c_str(), oj_port, nullptr, 0))
            {
                // 表示连接数据库失败
                LOG(FATAL) << "数据库连接失败！请尽快联系数据库管理员....." << "\n";
                return false;
            }
            // 连接成功后先执行编码格式
            mysql_set_character_set(oj_client, "utf8");
            mysql_query(oj_client, "SET NAMES utf8mb4;");
            // 连接成功后执行语句

            int result = mysql_query(oj_client, sql.c_str());
            if (result != 0)
            {
                // 执行失败
                LOG(WARING) << "当前sql执行失败: " << sql << " \n";
                return false;
            }
            // 执行成功，提取数据
            MYSQL_RES* res = mysql_store_result(oj_client);
            // 解析数据
            int rows = mysql_num_rows(res);  // 获取行数
            int fields = mysql_num_fields(res);  // 获取列数

            // 读取每一个元组，提取每一个元组的九个属性
            for (int i = 0; i < rows; ++i)
            {
                MYSQL_ROW line = mysql_fetch_row(res);
                Question q;
                q.number = line[0];
                q.title = line[1];
                q.star = line[2];
                q.cpu_commit = atoi(line[6]);
                q.mem_commit = atoi(line[7]);
                q.desc = line[3];
                q.header = line[4];
                q.tail = line[5];
                q.test_input = line[8];

                v.push_back(q);
            }
            // LOG(DEBUG) << "正常访问数据库成功..." << "\n";
            return true;
        }

        // 获取当前题目列表信息
        bool GetAllQuestions(std::vector<Question>& v)
        {
            std::string sql = "select * from ";
            sql += oj_table_name;
            return QueryMySql(sql, v);
        }

        // 获取单个题目信息，给我number
        // 已经提供日志差错处理
        bool GetOneQuestion(const std::string& number, Question& q)
        {
            std::string sql = "select * from ";
            sql += oj_table_name;
            sql += " where number=";
            sql += number;
            std::vector<Question> v;
            if (QueryMySql(sql, v))
            {
                if (v.size() == 1)
                {
                    // 只能存在一个记录
                    q = v[0];
                    return true;
                }
            }
            return false;
        }
    };
}

#endif
